﻿// Decompiled with JetBrains decompiler
// Type: DnProcessSimulateCommands.CApAPPKineoForAppTrajectorySegmentPlanCommand
// Assembly: DnProcessSimulateCommands, Version=2402.0.0.890, Culture=neutral, PublicKeyToken=null
// MVID: A885D881-AEDF-447E-852A-6F13102E089C
// Assembly location: C:\Program Files\Tecnomatix_2402\eMPower\DotNetCommands\DnProcessSimulateCommands.dll

using DnProcessSimulateCommands.AutomaticPathPlanner;
using DnProcessSimulateCommands.AutomaticPathPlanner.Planner;
using EngineeringInternalExtension;
using EngineeringInternalExtension.Viewers;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows.Forms;
using Tecnomatix.Engineering;


namespace DnProcessSimulateCommands;

public class CApAPPKineoForAppTrajectorySegmentPlanCommand : CApAPPPlanCommandBase
{
  private Stopwatch m_elapsedTimer;
  private long m_lastRefreshTime;
  private List<CApAPPSubTask> m_allSubtasksToPlan;
  private List<CApAPPSegmentPlanCommand> m_allSegmentPlanCommands;
  private CApAPPMagnetPoint m_magnetPoint;
  private readonly TxOperationTreeInternal m_operationTree;
  private int m_currentSubTaskIndex;
  private bool m_planningWasSkipped;
  private bool m_atLeastOneSuccess;
  private bool m_atLeastOneError;
  private bool m_mustShowLastAddedPosition;

  public CApAPPKineoForAppTrajectorySegmentPlanCommand(
    List<CApAPPTask> i_tasks,
    KiAppPathPlanningParamsEx i_pathPlanningParams)
    : base(i_tasks, i_pathPlanningParams)
  {
    this.m_elapsedTimer = new Stopwatch();
    this.m_lastRefreshTime = 0L;
    this.m_operationTree = new TxOperationTreeInternal();
    this.m_allSubtasksToPlan = this.GetAllSubtasksToPlan();
    this.PlanningWasCancelled = false;
    this.m_planningWasSkipped = false;
    this.m_atLeastOneSuccess = false;
    this.m_currentSubTaskIndex = -1;
    this.m_allSegmentPlanCommands = new List<CApAPPSegmentPlanCommand>();
    this.m_magnetPoint = (CApAPPMagnetPoint) null;
    this.m_mustShowLastAddedPosition = false;
  }

  private List<CApAPPSubTask> GetAllSubtasksToPlan()
  {
    List<CApAPPSubTask> allSubtasksToPlan = new List<CApAPPSubTask>();
    foreach (CApAPPTask capAppTask in this.TasksToPlan)
    {
      for (int i_index = 0; i_index < capAppTask.CountSubTasks(); ++i_index)
      {
        if (capAppTask.SubTask(i_index).IsToPlan())
          allSubtasksToPlan.Add(capAppTask.SubTask(i_index));
      }
    }
    return allSubtasksToPlan;
  }

  private CApAPPSegmentPlanCommand DoCreatePlanCommand(
    CApAPPSubTask i_subtask,
    KiAppPathPlanningParamsEx i_pathPlanningParams)
  {
    return new CApAPPSegmentPlanCommand(i_subtask, i_pathPlanningParams, false, CApAPPSegmentPlanOption.KineoForAppTrajectory);
  }

  protected override bool DoStart(
    ref CApAPPPlanCommandBase.PlanSuccessEventArgs errEvtArgs)
  {
    bool o_trackEndReached = false;
    bool flag1 = false;
    bool flag2 = false;
    this.m_operationTree.FreezeTree();
    while (!flag1 && !this.PlanningWasCancelled)
    {
      flag2 = this.StartNextPathPlanning(ref o_trackEndReached);
      if (flag2)
      {
        flag1 = o_trackEndReached;
        if (!flag1)
        {
          while (!this.m_allSegmentPlanCommands[this.m_currentSubTaskIndex].IsFinished() && !this.PlanningWasCancelled)
          {
            this.m_allSegmentPlanCommands[this.m_currentSubTaskIndex].onIdle();
            this.RefreshProgressUI();
          }
          if (this.PlanningWasCancelled && !this.m_allSegmentPlanCommands[this.m_currentSubTaskIndex].IsFinished())
            this.m_allSegmentPlanCommands[this.m_currentSubTaskIndex].Cancel();
          this.m_atLeastOneSuccess = this.m_atLeastOneSuccess || this.m_allSegmentPlanCommands[this.m_currentSubTaskIndex].WasPlanningSuccessful();
          this.m_atLeastOneError = this.m_atLeastOneError || !this.m_allSegmentPlanCommands[this.m_currentSubTaskIndex].WasPlanningSuccessful() && !this.m_allSegmentPlanCommands[this.m_currentSubTaskIndex].WasPlanningCancelled();
        }
      }
      else
        flag1 = true;
    }
    this.EndPlanning(this.PlanningWasCancelled || this.m_atLeastOneSuccess);
    return flag2;
  }

  private void RefreshProgressUI()
  {
    long elapsedMilliseconds = this.m_elapsedTimer.ElapsedMilliseconds;
    if (elapsedMilliseconds - this.m_lastRefreshTime <= 500L)
      return;
    this.m_lastRefreshTime = elapsedMilliseconds;
    this.UpdateProgress((object) this, new EventArgs());
    Application.DoEvents();
    this.HandlePlanningEvents();
  }

  public bool StartNextPathPlanning(ref bool o_trackEndReached)
  {
    bool flag = true;
    ++this.m_currentSubTaskIndex;
    o_trackEndReached = false;
    if (this.m_currentSubTaskIndex >= this.m_allSubtasksToPlan.Count)
    {
      o_trackEndReached = true;
    }
    else
    {
      flag = false;
      while (!flag && this.m_currentSubTaskIndex < this.m_allSubtasksToPlan.Count)
      {
        CApAPPSubTask i_subtask = this.m_allSubtasksToPlan[this.m_currentSubTaskIndex];
        this.m_planningWasSkipped = false;
        this.m_allSegmentPlanCommands.Add(this.DoCreatePlanCommand(i_subtask, this.PathPlanningParams));
        flag = this.m_allSegmentPlanCommands.Last<CApAPPSegmentPlanCommand>().StartPlanning();
        this.UpdatePlanSuccesses();
        if (flag)
        {
          this.m_elapsedTimer.Start();
        }
        else
        {
          this.m_atLeastOneError = true;
          ++this.m_currentSubTaskIndex;
        }
      }
      if (this.m_currentSubTaskIndex >= this.m_allSubtasksToPlan.Count)
        o_trackEndReached = true;
    }
    return flag;
  }

  public int CountPlanSubTasks()
  {
    int num = 0;
    foreach (CApAPPTask capAppTask in this.TasksToPlan)
      num += capAppTask.CountSubTasksToPlan();
    return num;
  }

  public override int RetrieveIndexSubProblemFromWaypoint(CApAPPWaypoint i_wp)
  {
    return this.RetrieveIndexSubTaskFromWaypoint(i_wp);
  }

  public override int CountSubProblems() => this.CountPlanSubTasks();

  public int RetrieveIndexSubTaskFromWaypoint(CApAPPWaypoint i_wp)
  {
    int num1 = 0;
    foreach (CApAPPTask capAppTask in this.TasksToPlan)
    {
      int num2 = capAppTask.RetrieveSubTaskIndexFromWaypoint(i_wp);
      if (num2 == -1)
      {
        num1 += capAppTask.CountSubTasksToPlan();
      }
      else
      {
        num1 += num2;
        break;
      }
    }
    return num1;
  }

  public void PlanNames(ref List<string> o_names)
  {
    o_names = new List<string>();
    foreach (CApAPPTask capAppTask in this.TasksToPlan)
    {
      for (int i_index = 0; i_index < capAppTask.CountSubTasksToPlan(); ++i_index)
      {
        string str = ((ITxObject) capAppTask.Operation).Name + " : " + capAppTask.SubTaskToPlan(i_index).Name();
        o_names.Add(str);
      }
    }
  }

  public override void CancelPlanning(int i_subtaskRank)
  {
    this.m_planningWasSkipped = true;
    if (this.m_allSegmentPlanCommands.Count <= i_subtaskRank)
      return;
    this.m_allSegmentPlanCommands[i_subtaskRank].Cancel();
    this.UpdateWaypointPlanSuccess(i_subtaskRank);
  }

  public override void Cancel()
  {
    this.PlanningWasCancelled = true;
    foreach (CApAPPSegmentPlanCommand segmentPlanCommand in this.m_allSegmentPlanCommands)
    {
      if (!segmentPlanCommand.IsFinished())
        segmentPlanCommand.Cancel();
    }
  }

  private List<CApAPPWaypointPlanSuccess> GetTaskPlanSuccess(CApAPPTask task)
  {
    int plan = task.CountSubTasksToPlan();
    List<CApAPPWaypointPlanSuccess> taskPlanSuccess = new List<CApAPPWaypointPlanSuccess>(plan);
    for (int i_index1 = 0; i_index1 < plan; ++i_index1)
    {
      int i_index2 = task.RetrieveWaypointIndexFromSubTask(task.SubTaskToPlan(i_index1));
      taskPlanSuccess.Add(task.Waypoint(i_index2).WaypointPlanSuccess);
    }
    return taskPlanSuccess;
  }

  protected override bool IsPlanned(CApAPPSubTask subtask) => subtask.IsToPlan();

  private void DoEndPlanning(bool i_success)
  {
    this.m_operationTree.UnFreezeTree();
    foreach (CApAPPTask task in this.TasksToPlan)
    {
      int i_subtaskRank = 0;
      List<CApAPPWaypointPlanSuccess> taskPlanSuccess = this.GetTaskPlanSuccess(task);
      if (taskPlanSuccess.Count == task.CountSubTasksToPlan())
      {
        for (int index = 0; index < task.CountSubTasksToPlan(); ++index)
        {
          if (this.IsPlanned(task.SubTaskToPlan(index)))
          {
            CApAPPWaypointPlanSuccess waypointPlanSuccess = this.GetPlanSuccess(i_subtaskRank);
            ++i_subtaskRank;
            if (waypointPlanSuccess == CApAPPWaypointPlanSuccess.WaitingBeforeCalc)
              waypointPlanSuccess = CApAPPWaypointPlanSuccess.Regular;
            taskPlanSuccess[index] = waypointPlanSuccess;
          }
        }
      }
      if (i_success)
        task.UpdateTxOperation();
      task.UpdatePlanSuccesses(taskPlanSuccess);
      task.RestoreInitialState();
    }
    if (this.m_allSubtasksToPlan.Last<CApAPPSubTask>().Task is CApAPPObjectFlowTask task1)
      task1.ResetGripPosition();
    TxApplication.RefreshDisplay();
  }

  private void EndPlanning(bool i_success)
  {
    this.DoEndPlanning(i_success);
    this.NotifyEndPlanning();
  }

  public override void UpdatePlanSuccesses()
  {
    for (int i_subtaskRank = 0; i_subtaskRank < this.CountSubProblems(); ++i_subtaskRank)
      this.UpdateWaypointPlanSuccess(i_subtaskRank);
    this.NotifyUpdateWaypointStatus();
  }

  private void HandlePlanningEvents()
  {
    if (this.m_currentSubTaskIndex >= this.m_allSubtasksToPlan.Count || !(this.m_allSubtasksToPlan[this.m_currentSubTaskIndex].Task is CApAPPObjectFlowTask task) || !this.m_mustShowLastAddedPosition)
      return;
    KiAppLocationEx kiAppLocationEx = (KiAppLocationEx) null;
    KiAppSegmentPlanCommandEx.GetLastAddedNode(this.m_allSubtasksToPlan[this.m_currentSubTaskIndex].KiSubTask, ref kiAppLocationEx);
    if (kiAppLocationEx == null)
      return;
    task.SetGripLocation(new TxTransformation(kiAppLocationEx.AbsoluteLocation));
    TxApplication.RefreshDisplay();
  }

  public override CApAPPWaypointPlanSuccess GetPlanSuccess(int i_subtaskRank)
  {
    CApAPPWaypointPlanSuccess planSuccess = CApAPPWaypointPlanSuccess.WaitingBeforeCalc;
    if (i_subtaskRank <= this.m_currentSubTaskIndex)
    {
      switch (this.m_allSegmentPlanCommands[i_subtaskRank].PlanSuccess())
      {
        case CApAPPPlanSuccess.SUCCESS:
          planSuccess = CApAPPWaypointPlanSuccess.CalcSuccess;
          break;
        case CApAPPPlanSuccess.SKIP:
          planSuccess = CApAPPWaypointPlanSuccess.Cancel;
          break;
        case CApAPPPlanSuccess.CLASH_ERROR:
          planSuccess = (CApAPPWaypointPlanSuccess) KiAppSegmentPlanCommandEx.GetPlanSuccess(this.m_allSubtasksToPlan[i_subtaskRank].KiSubTask);
          break;
        case CApAPPPlanSuccess.TIMEOUT_ERROR:
          planSuccess = CApAPPWaypointPlanSuccess.CalcFail;
          break;
        case CApAPPPlanSuccess.WAIT:
          planSuccess = CApAPPWaypointPlanSuccess.WaitingForCalc;
          break;
        case CApAPPPlanSuccess.WAIT_BEFORE_START:
          planSuccess = CApAPPWaypointPlanSuccess.WaitingBeforeCalc;
          break;
        case CApAPPPlanSuccess.SUCCESS_PREPROCESSING:
          planSuccess = CApAPPWaypointPlanSuccess.PreProcessingSuccess;
          break;
      }
    }
    return planSuccess;
  }

  public override long GetElapsedTime() => this.m_elapsedTimer.ElapsedMilliseconds;

  public bool GetPlanningStatus(int i_subtaskRank)
  {
    bool planningStatus = false;
    if (i_subtaskRank <= this.m_currentSubTaskIndex)
      planningStatus = !this.m_allSegmentPlanCommands[i_subtaskRank].IsFinished();
    return planningStatus;
  }

  public override bool IsFinished(int i_subtaskRank)
  {
    return i_subtaskRank <= this.m_currentSubTaskIndex && this.m_allSegmentPlanCommands[i_subtaskRank].IsFinished();
  }

  public override double GetProgress()
  {
    double num1 = 0.0;
    double num2 = (double) this.CountPlanSubTasks();
    for (int index = 0; index < this.m_currentSubTaskIndex; ++index)
      num1 += 1.0 / num2;
    return num1 + this.GetProgress(this.m_currentSubTaskIndex) / num2;
  }

  public override double GetProgress(int i_subtaskRank)
  {
    double progress = 0.0;
    if (i_subtaskRank <= this.m_currentSubTaskIndex && i_subtaskRank < this.m_allSegmentPlanCommands.Count)
      progress = this.m_allSegmentPlanCommands[i_subtaskRank].GetProgress();
    return progress;
  }

  public override void UpdateWaypointPlanSuccess(int i_subtaskRank)
  {
    if (i_subtaskRank >= this.m_allSubtasksToPlan.Count)
      return;
    CApAPPTask capAppTask = CApAPPTask.RetrieveSubTaskParentTask(this.m_allSubtasksToPlan[i_subtaskRank], this.TasksToPlan);
    if (capAppTask == null)
      return;
    int i_index = capAppTask.RetrieveWaypointIndexFromSubTask(this.m_allSubtasksToPlan[i_subtaskRank]);
    int num;
    switch (capAppTask.Waypoint(i_index).WaypointPlanSuccess)
    {
      case CApAPPWaypointPlanSuccess.Collision:
      case CApAPPWaypointPlanSuccess.SectionVolumeCollision:
      case CApAPPWaypointPlanSuccess.LocReachFail:
      case CApAPPWaypointPlanSuccess.OutOfLimits:
      case CApAPPWaypointPlanSuccess.TwistedCable:
      case CApAPPWaypointPlanSuccess.SingularityZone:
      case CApAPPWaypointPlanSuccess.PreProcessingSuccess:
        num = 0;
        break;
      default:
        num = capAppTask.Waypoint(i_index).WaypointStatus != CApAPPWaypointStatus.ReachFail ? 1 : 0;
        break;
    }
    if (num != 0)
    {
      capAppTask.Waypoint(i_index).WaypointPlanSuccess = this.GetPlanSuccess(i_subtaskRank);
    }
    else
    {
      if (capAppTask.Waypoint(i_index).WaypointStatus != CApAPPWaypointStatus.ReachFail)
        return;
      capAppTask.Waypoint(i_index).WaypointPlanSuccess = CApAPPWaypointPlanSuccess.LocReachFail;
    }
  }

  private void NotifyEndPlanning()
  {
    this.NotifyEndPlanning((object) this, new CApAPPPlanCommandBase.PlanSuccessEventArgs(this.WasPlanningProcessSuccessful(), CApAPPMainWindowStringTable.PathPlanningErrorTitle, this.ComputeErrorMessage()));
  }

  public bool WasPlanningProcessSuccessful()
  {
    return !this.m_atLeastOneError || this.PlanningWasCancelled || this.m_planningWasSkipped;
  }

  public string ComputeErrorMessage()
  {
    return $"{CApAPPMainWindowStringTable.PathPlanningErrorMsg}\r\n{CApAPPMainWindowStringTable.PathPlanningErrorCheckLocationStatusMsg}";
  }

  internal override bool IsMagnetPointEnabled()
  {
    return this.m_magnetPoint != null && this.m_magnetPoint.IsActivated();
  }

  internal override void ToggleMagnetPoint()
  {
    if (this.IsMagnetPointEnabled())
    {
      this.m_magnetPoint.Deactivate();
    }
    else
    {
      if (!(this.m_allSubtasksToPlan[this.m_currentSubTaskIndex].Task is CApAPPObjectFlowTask task))
        return;
      if (this.m_magnetPoint == null)
      {
        try
        {
          this.m_magnetPoint = new CApAPPMagnetPoint(task);
        }
        catch (CApAPPMagnetPoint.MagnetPointCreationFailedException ex)
        {
          this.m_magnetPoint = (CApAPPMagnetPoint) null;
        }
      }
      if (this.m_magnetPoint != null)
        this.m_magnetPoint.Activate();
      this.SetMagnetPointPositionToStartPosition();
    }
  }

  internal override void ClearMagnetPoint()
  {
    if (this.m_magnetPoint == null)
      return;
    this.m_magnetPoint.Deactivate();
    this.m_magnetPoint.ClearData();
    this.m_magnetPoint = (CApAPPMagnetPoint) null;
  }

  internal override void SetMagnetPointPositionToLastAddedNode()
  {
    if (this.m_magnetPoint == null)
      return;
    KiAppLocationEx kiAppLocationEx = (KiAppLocationEx) null;
    KiAppSegmentPlanCommandEx.GetLastAddedNode(this.m_allSubtasksToPlan[this.m_currentSubTaskIndex].KiSubTask, ref kiAppLocationEx);
    if (kiAppLocationEx == null)
      return;
    this.m_magnetPoint.SetPosition(new TxTransformation(kiAppLocationEx.AbsoluteLocation));
  }

  internal void SetMagnetPointPositionToStartPosition()
  {
    if (this.m_magnetPoint == null)
      return;
    this.m_magnetPoint.SetPosition(new TxTransformation(this.m_allSubtasksToPlan[this.m_currentSubTaskIndex].Task.Waypoint(this.m_allSubtasksToPlan[this.m_currentSubTaskIndex].KiSubTask.SourceWaypointIndex).SimulatedApproachLocation.AbsoluteLocation));
  }

  internal override KiAppPlanningStep GetCurrentPlanningStep()
  {
    KiAppPlanningStep currentPlanningStep = (KiAppPlanningStep) 0;
    if (this.m_currentSubTaskIndex < this.m_allSubtasksToPlan.Count)
      currentPlanningStep = KiAppSegmentPlanCommandEx.GetCurrentPlanningStep(this.m_allSubtasksToPlan[this.m_currentSubTaskIndex].KiSubTask);
    return currentPlanningStep;
  }

  internal override void EnableShowLastAddedPosition() => this.m_mustShowLastAddedPosition = true;

  internal override void DisableShowLastAddedPosition()
  {
    if (this.m_currentSubTaskIndex < this.m_allSubtasksToPlan.Count && this.m_allSubtasksToPlan[this.m_currentSubTaskIndex].Task is CApAPPObjectFlowTask task)
    {
      task.ResetGripPosition();
      TxApplication.RefreshDisplay();
    }
    this.m_mustShowLastAddedPosition = false;
  }

  internal override void AfterPlanningFailure() => this.m_operationTree.UnFreezeTree();
}
